#include<vector>
#include<list>
#include<algorithm>
#include<iostream>

#include "compare.h"

using namespace std;

template <class T, class CLCT>
class tContainer_t
{
    typedef typename CLCT::const_iterator iter_t;
public:
	//*************************************************************************
	// Default CTOR
	//*************************************************************************
    tContainer_t(){};
	//*************************************************************************
	// DTOR
	//*************************************************************************
	~tContainer_t()
	{
		iter_t iter;
		
		for(iter = cont.begin() ; iter != cont.end() ; ++iter)
		{
			delete(*iter);	
		}
	};
	//*************************************************************************
	// Return true/false according to if container empty or not
	//*************************************************************************
    bool isEmpty() const
	{
		return cont.empty();
	};
	//*************************************************************************
	// Return number of elements in container
	//*************************************************************************
    int getNumElem() const
	{
		return cont.size();
	};
	//*************************************************************************
	// Return first element in container
	//*************************************************************************
    T* getFirstElem() const
	{
		return cont.front();
	};
	//*************************************************************************
	// Return last element in container
	//*************************************************************************
    T* getLastElem() const
	{
		return cont.back();
	};
	//*************************************************************************
	// Find specific element by value
	//*************************************************************************
    const T* findElem(const T& t) const
	{
		iter_t it = find_if(cont.begin(), cont.end(), compare<T>(t));
		return ((it!=cont.end()) ? *it : NULL) ;
	};
	//*************************************************************************
	// Remove specific element and return pointer to it
	//*************************************************************************
    const T* removeElem(const T& t)
	{
		iter_t it = find_if(cont.begin(), cont.end(), compare<T>(t));
		if (it==cont.end()) return NULL;
		
		T* temp = *it;
		cont.erase(it);

		return temp;
	};
	//*************************************************************************
	// Remove all elements without deleting them (return 1 if succeeded)
	//*************************************************************************
    int removeAll()
	{
/*
		vector<int> temp;
		iter_t it;
		for(it = cont.begin() ; it != cont.end() ; it++)
		{
			temp.push_back(**it);
		}
*/		
		cont.clear();
/*
        vector<int>::const_iterator it1;
		for(it1 = temp.begin() ; it1 != temp.end() ; it1++)
		{
			cout << *it1;
		}
		cout << endl;
*/
		return 1;
	};
	//*************************************************************************
	// Remove and delete specific element (return 1 if succeeded)
	//*************************************************************************
    int removeDeleteElem(const T& t)
	{
		iter_t it = find_if(cont.begin(), cont.end(), compare<T>(t));
		if (it==cont.end()) return 0;
		
		delete(*it);
		cont.erase(it);

		return 1;
	};
	//*************************************************************************
	// Operator[]
	//*************************************************************************
    T*& operator[](unsigned i) const
	{
		if (i>cont.size()) 
		{
			cout << "ERROR: the index is out of range" << endl;
			exit(0);
		}

		iter_t iter;
		iter = cont.begin();
		
		while(i>0)
		{
			iter++;
			i--;
		}
		
		return (T*)*iter;
	};
	//*************************************************************************
	// Operator+=
	//*************************************************************************
    tContainer_t& operator+=(tContainer_t& cCont) 
	{
		iter_t iter;
		
		for (iter = cCont.cont.begin() ; iter!=cCont.cont.end() ; iter++)
		{
			this->cont.push_back(*iter);
		}

		cCont.cont.clear();

		return *this;

	}

	//*************************************************************************
	// Insert a new element at the end of container (return 1 if succeeded)
	//*************************************************************************
	int insertElem(const T& elem)
	{
		T* pT = new T;
		*pT = elem;
		cont.push_back(pT);

		return 1;
	};
	//*************************************************************************
	// Print out all elemnts of the container
	//*************************************************************************
	void printOut() const
	{
		iter_t it;
		for(it = cont.begin() ; it != cont.end() ; it++)
		{
			cout << **it << " ";
		}

		cout << endl;
	};

private:
	tContainer_t(const tContainer_t&);     //copy CTOR

    CLCT cont;            // STL container (vector or list)
};